package com.lyh.system.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConstants;
import com.alipay.api.domain.AlipayFundTransUniTransferModel;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.Participant;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lyh.common.core.domain.AjaxResult;
import com.lyh.common.core.domain.BaseEntity;
import com.lyh.common.core.domain.entity.SysUser;
import com.lyh.common.enums.*;
import com.lyh.common.exception.ServiceException;
import com.lyh.common.utils.SecurityUtils;
import com.lyh.common.utils.StringUtils;
import com.lyh.common.utils.http.HttpClientUtil;
import com.lyh.system.biz.IOrderBiz;
import com.lyh.system.biz.IPayBiz;
import com.lyh.system.domain.*;
import com.lyh.system.domain.req.WxPrepareReq;
import com.lyh.system.domain.req.ZfbCashAdvanceReq;
import com.lyh.system.domain.req.ZfbPayCommonReq;
import com.lyh.system.domain.resp.WxPayInfoResp;
import com.lyh.system.mapper.*;
import com.lyh.system.service.IPayService;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import lombok.extern.log4j.Log4j2;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.security.GeneralSecurityException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@Log4j2
public class PayServiceImpl implements IPayService {
    //预下单
    private String getPrepayId  = "https://api.mch.weixin.qq.com/v3/pay/transactions/app";
    //退款
    private String refunds = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";

    @Value("${wx.appid}")
    private String appid;

    @Value("${wx.mchid:}")
    private String mchid;

    @Value("${wx.notify_url:}")
    private String notifyUrl;

    @Value("${wx.key:}")
    private String apiV3Key;


     @Autowired
     private OrderMapper orderMapper;

    @Autowired
    private RechargeRecordMapper rechargeRecordMapper;

     @Autowired
     private GoodsMapper goodsMapper;

    @Autowired
     private RedissonClient  redissonClient;

    @Autowired
    private IPayBiz payBiz;
    @Autowired
    private UserPayRecordMapper userPayRecordMapper;

    @Autowired
    private UserRefunfRecordMapper userRefunfRecordMapper;

    @Autowired
    private OperationInfoMapper operationInfoMapper;

    @Autowired
    private AssetMapper assetMapper;

   //支付宝相关
    @Autowired
    private AlipayClient alipayClient;

    @Autowired
    private  IOrderBiz orderBiz;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Value("${alipay.return-url:}")
    private String returnUrl;

    @Value("${alipay.merchant-private-key:}")
    private String privateKey;

    @Value("${alipay.alipay-public-key:}")
    private String publicKey;

    @Value("${alipay.seller-id:}")
    private String sellerId;

    @Value("${alipay.app.id:}")
    private String appId;

    @Value("${alipay.alipayPublicCert:}")
    private String alipayPublicCert;

    @Value("${isTest}")
    private boolean isTest = false;

    @Autowired
    private UserCashAdvanceMapper userCashAdvanceMapper;

/*    @Autowired
    private WxPayConfig wxPayConfig;

    @Autowired
    private Verifier verifier;*/

/*    {
        "mchid": "1900006XXX",
        "out_trade_no": "APP1217752501201407033233368018",
        "appid": "wxb4ba3c02aa476XXX",
        "description": "Image形象店-深圳腾大-QQ公仔",
        "notify_url": "https://weixin.qq.com/",
        "amount": {
            "total": 1,
            "currency": "CNY"
                }
    }*/

    @Override
    public String getPrepayId(WxPrepareReq req) {
        Order order = orderMapper.selectById(req.getOrderId());
        Goods goods = goodsMapper.selectById(order.getGoodsId());
        String key = "pay_order"+order.getId();
        RLock lock = redissonClient.getLock(key);
        String result = null;
        try {
            if(lock.tryLock(30, 30, TimeUnit.SECONDS)){
                Map<String, Object> map = new HashMap<>();
                map.put("appid",appid);//应用ID
                map.put("mchid",mchid);//直连商户号
                map.put("description",goods.getName());//商品描述
                map.put("out_trade_no",order.getOrderNum());//商户订单号
                map.put("notify_url",notifyUrl);//通知地址
                Map<String, Object> amountMap = new HashMap<>();
                amountMap.put("total",order.getActualPayment().multiply(new BigDecimal(100)).intValue());//订单金额-精确到分
                amountMap.put("currency","CNY");
                map.put("amount",amountMap);
                String json = JSONObject.toJSONString(map);
                log.info("rep="+json);
                //保存支付记录
                payBiz.savaPayRecordPrepare(order,json);
                String post = HttpClientUtil.doPost(getPrepayId, json, "utf-8");
                if(StringUtils.isNotEmpty(post)){
                    log.info(JSONObject.toJSONString(map)+"resp="+post);
                    JSONObject jsonObject = JSONObject.parseObject(post);
                    String prepayId = jsonObject.getString("prepay_id");
                    if(StringUtils.isNotEmpty(prepayId)){
                        result = prepayId;
                    }else{
                        String codeStr = jsonObject.getString("code");
                        result = WxErrorCodeEnum.getEnum(codeStr).getMsg();
                        throw new ServiceException(result);
                    }
                }
                System.out.println(post);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (Exception e) {
            log.error("调用微信下单错误", e);
            throw new ServiceException(result);
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        //获取订单ID
        return result;
    }

    @Override
    public AjaxResult wehcatPayCallback(HttpServletRequest request, HttpServletResponse response) {
       /* WxPayInfoResp wxPayInfoResp = null;
        Gson gson = new Gson();
        //获取报文
        String body = getRequestBody(request);
        HashMap<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
        //构造签名串
        //应答时间戳\n
        //应答随机串\n
        //应答报文主体\n

            //验证签名是否通过
            WechatPayValidatorForRequest wechatForRequest = new WechatPayValidatorForRequest(verifier, body, (String) bodyMap.get("id"));
            try {
                if (!wechatForRequest.validate(request)) {
                    // 通知验签失败
                    response.setStatus(500);
                    final HashMap<String, Object> map = new HashMap<>();
                    map.put("code", "ERROR");
                    map.put("message", "通知验签失败");
                    return AjaxResult.error(JSONObject.toJSONString(map));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            //解密数据
        String plainBody = null;
        try {
            plainBody = decryptBody(body);
            log.info("解密后的明文:{}", plainBody);
            wxPayInfoResp = JSONObject.parseObject(plainBody, WxPayInfoResp.class);
            if (wxPayInfoResp.getTrade_state().equals("SUCCESS")) {
                //支付成功,更新订单信息
                payBiz.updatePayRecordInfo(wxPayInfoResp, plainBody);
            } else if (wxPayInfoResp.getTrade_state().equals("NOTPAY")) {
                payBiz.updatePayRecordInfo(wxPayInfoResp, plainBody);
            } else if (wxPayInfoResp.getTrade_state().equals("CLOSED")) {
                payBiz.updatePayRecordInfo(wxPayInfoResp, plainBody);
            } else {
                throw new ServiceException("支付失败！");
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
       }*/
        return AjaxResult.success();

    }



    /**
     *  描述：支付宝测试网页支付
     *
     * @Author：Ljx
     * @Date 2023/7/7 17:51
     * @param
     * @Return
    **/
    @Override
    public String tradeCreate() {
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        //支付宝公共参数
        request.setNotifyUrl(returnUrl);
        request.setReturnUrl("");

        //面向对象封装业务参数
        AlipayTradePagePayModel model =new AlipayTradePagePayModel();
        model.setOutTradeNo("20220801214100021");
        model.setTotalAmount("0.1");
        model.setSubject("品牌大使推广产品");
        model.setProductCode("FAST_INSTANT_TRADE_PAY");

        //bizContent.put("time_expire", "2022-08-01 22:00:00");

        //商品明细信息，按需传入
        //JSONArray goodsDetail = new JSONArray();
        //JSONObject goods1 = new JSONObject();
        //goods1.put("goods_id", "goodsNo1");
        //goods1.put("goods_name", "子商品1");
        //goods1.put("quantity", 1);
        //goods1.put("price", 0.01);
        //goodsDetail.add(goods1);
        //bizContent.put("goods_detail", goodsDetail);

        //扩展信息，按需传入
        //JSONObject extendParams = new JSONObject();
        //extendParams.put("sys_service_provider_id", "2088511833207846");
        //bizContent.put("extend_params", extendParams);

       // request.setBizContent(bizContent.toString());
        request.setBizModel(model);
        //执行请求,调用支付宝
        AlipayTradePagePayResponse response = null;
        try {//pageExecute
            //网页支付
            response = alipayClient.pageExecute(request);
            //response = alipayClient.sdkExecute(request);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        if (response.isSuccess()) {
            log.info("调用成功,返回结果:[{}]",response.getBody());
            return response.getBody();
        } else {
            log.info("调用失败!!");
        }
        return  null;


    }



    /**
     *  描述：支付宝回调
     *
     * @Author：Ljx
     * @Date 2023/7/7 17:51
     * @param params
     * @Return
    **/
    @Override
    public String tradeNotify(Map<String, String> params) {
    String result = "failure";
    try {
        //异步通知验签
        boolean signVerified = AlipaySignature.rsaCertCheckV1(params,
                alipayPublicCert,
                AlipayConstants.CHARSET_UTF8,
                AlipayConstants.SIGN_TYPE_RSA2);
        if (!signVerified) {
            // TODO 验签失败则记录异常日志，并在response中返回failure.
            log.error("支付成功,异步通知验签失败!");
            return result;
        }
        log.info("支付成功,异步通知验签成功!");
        //TODO 验签成功后，按照支付结果异步通知中的描述，对支付结果中的业务内容进行二次校验
        //1.验证out_trade_no 是否为商家系统中创建的订单号
        String outTradeNo = params.get("out_trade_no");
        //查询支付记录
        List<UserPayRecordDO> userPayRecordDOS = userPayRecordMapper.selectList(new LambdaQueryWrapper<UserPayRecordDO>()
                .eq(UserPayRecordDO::getSysOrderNum, outTradeNo)
                .eq(UserPayRecordDO::getStatus,PayStatusEnum.WAIT.getCode())
                .orderByAsc(BaseEntity::getCreateTime));
        if(userPayRecordDOS==null || userPayRecordDOS.size()== 0){
            log.error("非本系统订单！");
            return result;
        }
        UserPayRecordDO recordDO = userPayRecordDOS.get(0);
        String sourceType = recordDO.getSourceType();
        //判断是否是本系统支付的订单
        if (!isTest && OrderIsValid(params, result, outTradeNo, sourceType)) {
            return result;
        }
        //3.校验通知中的 seller_id是否为 out_trade_no 这笔单据的对应的操作方
        String sellerId = params.get("seller_id");
        if (!sellerId.equals(sellerId)) {
            log.error("商家PID校验失败");
            return result;
        }
        //4.验证 app_id 是否为该商家本身
        String appId = params.get("app_id");
        if (!appId.equals(appId)){
            log.error("app_id校验失败");
            return result;
        }
        //在支付宝的业务通知中，只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时，支付宝才会认定为买家付款成功
        String tradeStatus = params.get("trade_status");
        if (!"TRADE_SUCCESS".equals(tradeStatus) && !"TRADE_FINISHED".equals(tradeStatus)){
            log.error("支付未成功");
        }else{
            log.error("支付成功");
            result = "success";
        }
        //处理自己业务
        dealPayCall(params, result,recordDO);
    } catch (AlipayApiException e) {
        e.printStackTrace();
    }
    return result;

   }

   /**
    *  描述：验证订单是否有效
    *
    * @Author：Ljx
    * @Date 2023/7/7 18:04
    * @param params
    * @param result
    * @param outTradeNo
    * @param sourceType
    * @Return
   **/
    private boolean OrderIsValid(Map<String, String> params, String result, String outTradeNo, String sourceType) {
        if(sourceType.equals("order")){
            List<Order> orders = orderMapper.selectList(new LambdaQueryWrapper<Order>()
                    .eq(Order::getOrderNum, outTradeNo));
            if(orders==null || orders.size() == 0){
                log.error(outTradeNo+"非本系统订单！");
                return true;
            }
            //2.判断 total_amount 是否确实为该订单的实际金额
            String totalAmount = params.get("total_amount");
            Order order = orders.get(0);
            if(order.getActualPayment().compareTo(new BigDecimal(totalAmount)) !=0){
                log.error(outTradeNo+"非该订单金额！");
                return true;
            }

        }else if(sourceType.equals("recharge")){
            //todo 若是消费卷或者资产需继续判断
            List<RechargeRecord> rechargeRecords = rechargeRecordMapper.selectList(new LambdaQueryWrapper<RechargeRecord>()
                    .eq(RechargeRecord::getOrderId, outTradeNo));
            if(rechargeRecords==null || rechargeRecords.size() == 0){
                log.error(outTradeNo+"非本系统订单！");
                return true;
            }
            //2.判断 total_amount 是否确实为该订单的实际金额
            String totalAmount = params.get("total_amount");
            RechargeRecord rechargeRecord = rechargeRecords.get(0);
            if(rechargeRecord.getRechargeAmount().compareTo(new BigDecimal(totalAmount)) !=0){
                log.error(outTradeNo+"非该订单金额！");
                return true;
            }
            return false;
        }
        return false;
    }

    /**
    *  描述：回调成功，处理自身业务
    *
    * @Author：Ljx
    * @Date 2023/7/7 17:52
    * @param params
    * @param result
    * @param userPayRecordDO
    * @Return
   **/
    void dealPayCall(Map<String, String> params,String result,UserPayRecordDO userPayRecordDO){
        if(result.equals("success")){
            String tradeNo = params.get("trade_no");
            userPayRecordDO.setPayOrderNum(tradeNo);
            userPayRecordDO.setStatus(PayStatusEnum.SUCCESS.getCode());
            userPayRecordMapper.updateById(userPayRecordDO);
            switch (userPayRecordDO.getSourceType()){
                case "order":
                    Order order = orderMapper.selectById(userPayRecordDO.getOrderId());
                    order.setPayTime(new Date());
                    order.setStatus(StoreOrderStatusEnum.wait_send.name());
                    OperationInfo info = new OperationInfo();
                    info.setUserId(order.getUserId());
                    info.setStatus(OperationStatusEnum.EXPENSE.name());
                    info.setOperationTime(new Date());
                    info.setOrigin(OperationOriginEnum.BUG_GOODS.name());
                    info.setType(OperationTypeEnum.CASH.name());
                    info.setPrice(order.getActualPayment());
                    operationInfoMapper.insert(info);
                    orderMapper.updateById(order);
                    SysUser sysUser = sysUserMapper.selectById(order.getUserId());
                    orderBiz.orderRebate(order,sysUser);
                    break;
                case "recharge":
                    RechargeDeal(userPayRecordDO);
                    break;
            }
        }else{
            switch (userPayRecordDO.getSourceType()){
                case "order":
                    Order order = orderMapper.selectById(userPayRecordDO.getOrderId());
                    order.setStatus(StoreOrderStatusEnum.fail.name());
                    OperationInfo info = new OperationInfo();
                    info.setUserId(order.getUserId());
                    info.setStatus(OperationStatusEnum.EXPENSE.name());
                    info.setOperationTime(new Date());
                    info.setOrigin(OperationOriginEnum.BUG_GOODS.name());
                    info.setType(OperationTypeEnum.CASH.name());
                    info.setPrice(order.getActualPayment());
                    operationInfoMapper.insert(info);
                    orderMapper.updateById(order);
                    break;
                case "recharge":
                    RechargeRecord rechargeRecord = rechargeRecordMapper.selectById(userPayRecordDO.getOrderId());
                    rechargeRecord.setRechargeTime(new Date());
                    rechargeRecord.setPaymentStatus(RechargeStatusEnum.FAIL.name());
                    rechargeRecordMapper.updateById(rechargeRecord);
                    break;
            }
        }



    }

    @Transactional
    public void RechargeDeal(UserPayRecordDO userPayRecordDO) {
        RechargeRecord rechargeRecord = rechargeRecordMapper.selectById(userPayRecordDO.getOrderId());
        rechargeRecord.setRechargeTime(new Date());
        rechargeRecord.setPaymentStatus(RechargeStatusEnum.SUCCESS.name());
        rechargeRecordMapper.updateById(rechargeRecord);
        //添加收支记录
        OperationInfo oi = new OperationInfo();
        oi.setUserId(rechargeRecord.getUserId());
        Asset asset = assetMapper.selectAssetByUserId(rechargeRecord.getUserId());
        if (OperationTypeEnum.CASH.name().equals(rechargeRecord.getRechargeType())) {
            asset.setAccountBalance(asset.getAccountBalance().add(rechargeRecord.getRechargeAmount()));
            oi.setType(OperationTypeEnum.CASH.name());
        } else if (OperationTypeEnum.ASSET_EVIDENCE.name().equals(rechargeRecord.getRechargeType())) {
            asset.setAssetEvidenceNum(asset.getAssetEvidenceNum().add(rechargeRecord.getRechargeAmount()));
            oi.setType(OperationTypeEnum.ASSET_EVIDENCE.name());
        } else if (OperationTypeEnum.CONSUMER_COUPON.name().equals(rechargeRecord.getRechargeType())) {
            asset.setConsumerCouponNum(asset.getConsumerCouponNum().add(rechargeRecord.getRechargeAmount()));
            oi.setType(OperationTypeEnum.CONSUMER_COUPON.name());
        }
        oi.setStatus(OperationStatusEnum.INCOME.name());
        oi.setOperationTime(new Date());
        oi.setPrice(rechargeRecord.getRechargeAmount());
        oi.setOrigin(OperationOriginEnum.RECHARGE.name());
        operationInfoMapper.insert(oi);
        assetMapper.updateById(asset);
    }

    /**
     *  描述：支付封装
     *
     * @Author：Ljx
     * @Date 2023/7/7 17:49
     * @param orderCommom
     * @Return
    **/
    @Override
    public String zfbPayCommom(ZfbPayCommonReq orderCommom){

        AlipayTradeAppPayRequest  request = new AlipayTradeAppPayRequest();
        //支付宝公共参数
        request.setNotifyUrl(returnUrl);
        request.setReturnUrl("");
        //面向对象封装业务参数
        AlipayTradePagePayModel model =new AlipayTradePagePayModel();
        model.setOutTradeNo(orderCommom.getOrderNum());
        if(isTest){
            model.setTotalAmount("0.01");
        }else{
            model.setTotalAmount(orderCommom.getTotalAmount());
        }

        model.setSubject(orderCommom.getGoodsName());
        model.setProductCode("QUICK_MSECURITY_PAY");
        request.setBizModel(model);
        //执行请求,调用支付宝
        AlipayTradeAppPayResponse response = null;
        UserPayRecordDO aDo = new UserPayRecordDO();
        try {

            aDo.setOrderId(orderCommom.getBusinessId());
            aDo.setPayType(AdvanceTypeEnum.zfb.getCode());
            aDo.setSysOrderNum(orderCommom.getOrderNum());
            aDo.setUserId(SecurityUtils.getLoginUser().getUserId());
            aDo.setPayMoney(new BigDecimal(orderCommom.getTotalAmount()).multiply(new BigDecimal(100)));
            aDo.setReqBody(JSONObject.toJSONString(request));
            aDo.setSourceType(orderCommom.getOrderSource());
            response = alipayClient.sdkExecute(request);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        if (response.isSuccess()) {
            log.info("调用成功,返回结果:[{}]",response.getBody());
            aDo.setStatus(PayStatusEnum.WAIT.getCode());
            aDo.setRespBody(response.getBody());
            userPayRecordMapper.insert(aDo);
            return response.getBody();
        } else {
            log.info("调用失败!!");
            aDo.setStatus(PayStatusEnum.FAIL.getCode());
            aDo.setRespBody(response.toString());
            userPayRecordMapper.insert(aDo);
        }
        return  null;

    }

    /**
     *  描述： 支付宝请求
     *
     * @Author：Ljx
     * @Date 2023/7/5 15:02
     * @param order
     * @Return
    **/
    @Override
    public String zfbPay(Order order) {
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        //支付宝公共参数
        request.setNotifyUrl(returnUrl);
        request.setReturnUrl("");
        //面向对象封装业务参数
//        AlipayTradePagePayModel model =new AlipayTradePagePayModel();
//        model.setOutTradeNo(order.getOrderNum());
//        model.setTotalAmount(order.getActualPayment().toString());
//      //  Goods goods = goodsMapper.selectById(order.getGoodsId());
//        model.setSubject("充值");
//
//        model.setProductCode("FAST_INSTANT_TRADE_PAY");
//        request.setBizModel(model);

        AlipayTradePagePayModel model =new AlipayTradePagePayModel();
        model.setOutTradeNo(order.getOrderNum());
        model.setTotalAmount(order.getActualPayment().toString());
        model.setSubject("充值");
        model.setProductCode("FAST_INSTANT_TRADE_PAY");
        request.setBizModel(model);

        //执行请求,调用支付宝
        AlipayTradePagePayResponse response = null;
        UserPayRecordDO aDo = new UserPayRecordDO();
        try {

            aDo.setOrderId(order.getId());
            aDo.setPayType(AdvanceTypeEnum.zfb.getCode());
            aDo.setSysOrderNum(order.getOrderNum());
            aDo.setSourceType("recharge");
            aDo.setUserId(11l);
            aDo.setPayMoney(order.getActualPayment().multiply(new BigDecimal(100)));
            aDo.setReqBody(JSONObject.toJSONString(request));
            response = alipayClient.pageExecute(request);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        if (response.isSuccess()) {
            log.info("调用成功,返回结果:[{}]",response.getBody());
            aDo.setStatus(PayStatusEnum.WAIT.getCode());
            aDo.setRespBody(response.getBody());
            userPayRecordMapper.insert(aDo);
            return response.getBody();
        } else {
            log.info("调用失败!!");
            aDo.setStatus(PayStatusEnum.FAIL.getCode());
            aDo.setRespBody(response.toString());
            userPayRecordMapper.insert(aDo);
        }
        return  null;
    }
    /**
     *  描述：支付宝退款（直接返回无回调）
     *
     * @Author：Ljx
     * @Date 2023/7/7 17:49
     * @param order
     * @Return
    **/
    @Override
    public String zfbRefund(Order order) {
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        List<UserPayRecordDO> userPayRecordDOS = userPayRecordMapper.selectList(new LambdaQueryWrapper<UserPayRecordDO>()
                .eq(UserPayRecordDO::getSysOrderNum, order.getOrderNum())
                .eq(UserPayRecordDO::getStatus, PayStatusEnum.SUCCESS.getCode()));
        if(userPayRecordDOS == null || userPayRecordDOS.size() == 0){
            throw new ServiceException("未找到该支付记录!");
        }
        UserPayRecordDO payRecord = userPayRecordDOS.get(0);
        JSONObject bizContent = new JSONObject();
        bizContent.put("trade_no", payRecord.getPayOrderNum());
        if(isTest){
            bizContent.put("refund_amount", "0.01");
        }else{
            bizContent.put("refund_amount", order.getActualPayment());
        }

        bizContent.put("out_request_no", payRecord.getSysOrderNum());
        request.setBizContent(bizContent.toString());
        AlipayTradeRefundResponse response = null;
        try {
            response = alipayClient.execute(request);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        if(response.isSuccess()){
            saveRefundRecord(request,response,PayStatusEnum.SUCCESS.getCode());
            dealSuccessRefundData(payRecord,StoreOrderStatusEnum.refund_success.name());
            System.out.println("调用成功");
            return StoreOrderStatusEnum.refund_success.name();
        } else {
            saveRefundRecord(request,response,PayStatusEnum.FAIL.getCode());
            dealSuccessRefundData(payRecord,StoreOrderStatusEnum.refund_on.name());
            System.out.println("调用失败");
            return StoreOrderStatusEnum.refund_on.name();
        }

    }

    @Override
    public boolean zfbCashAdvance(ZfbCashAdvanceReq req) {


        UserCashAdvance cashAdvance = userCashAdvanceMapper.selectById(req.getAdvanceId());
        if(cashAdvance == null){
            throw new ServiceException("未找到当前转账记录");
        }
        boolean result;
        AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
        AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
        /** 商户端的唯一订单号，对于同一笔转账请求，商户需保证该订单号唯一 **/
        model.setOutBizNo(cashAdvance.getOrderNum());
        /** 转账金额，TRANS_ACCOUNT_NO_PWD产品取值最低0.1  **/
        if(isTest){
            model.setTransAmount("0.1");
        }else{
            BigDecimal serviceFee = cashAdvance.getServiceFee();
            if(serviceFee==null){
                serviceFee = new BigDecimal(0);
            }
            BigDecimal subtract = cashAdvance.getAdvanceMoney().subtract(serviceFee);
            model.setTransAmount(subtract.toString());
        }
        /** 产品码，单笔无密转账到支付宝账户固定为：TRANS_ACCOUNT_NO_PWD **/
        model.setProductCode("TRANS_ACCOUNT_NO_PWD");
        /** 场景码，单笔无密转账到支付宝账户固定为：DIRECT_TRANSFER  **/
        model.setBizScene("DIRECT_TRANSFER");
        /** 转账业务的标题，用于在支付宝用户的账单里显示 **/
        model.setOrderTitle(req.getTitle());
        Participant participant = new Participant();
        /** 参与方的唯一标识,收款支付宝账号或者支付宝吧账号唯一会员ID **/
        participant.setIdentity(req.getZfbAccount());
        /** 参与方的标识类型：ALIPAY_USER_ID 支付宝的会员ID  **/
        participant.setIdentityType("ALIPAY_LOGON_ID");
        /** 参与方真实姓名，如果非空，将校验收款支付宝账号姓名一致性。当identity_type=ALIPAY_LOGON_ID时，本字段必填 **/
        participant.setName(req.getRealName());
        model.setPayeeInfo(participant);
        /** 业务备注  **/
        model.setRemark("单笔转账");
        request.setBizModel(model);
        AlipayFundTransUniTransferResponse response = null;
        try {
            response = alipayClient.certificateExecute(request);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        if (response.isSuccess() && response.getStatus().equals("SUCCESS")) {
            log.info(req.toString()+"调用成功");
            cashAdvance.setResp(response.getBody());
            cashAdvance.setZfbOrderNum(response.getPayFundOrderId());
            cashAdvance.setStatus(AdvanceStatusEnum.success.name());
            cashAdvance.setAuditUserId(SecurityUtils.getLoginUser().getUserId());
            cashAdvance.setAuditTime(new Date());
            result = true;
        } else {
            cashAdvance.setResp("调用失败:"+response.getBody());
            cashAdvance.setStatus(AdvanceStatusEnum.fail.name());
            result = false;
        }
        System.out.println(response.getBody());
        userCashAdvanceMapper.updateById(cashAdvance);
        return result;
    }

    //退款业务处理

    void saveRefundRecord(AlipayTradeRefundRequest request,
                         AlipayTradeRefundResponse response,String status){
        UserRefundRecordDO refundDo = new UserRefundRecordDO();
        refundDo.setUserId(SecurityUtils.getLoginUser().getUserId());
        refundDo.setStatus(status);
        refundDo.setSysOrderNum(response.getOutTradeNo());
        refundDo.setReqBody(JSONObject.toJSONString(request));
        refundDo.setRespBody(JSONObject.toJSONString(response));
        refundDo.setPayType(AdvanceTypeEnum.zfb.getCode());
        refundDo.setOriPayMoney(new BigDecimal(response.getRefundFee()));
        refundDo.setRefundOrderNum(response.getTradeNo());
        userRefunfRecordMapper.insert(refundDo);

    }
    @Transactional
    void dealSuccessRefundData(UserPayRecordDO payRecord,String statusEnums){

       //查找订单
       Order oriOrder = orderMapper.selectById(payRecord.getOrderId());
       oriOrder.setStatus(statusEnums);
       orderMapper.updateById(oriOrder);

    }




    /**
     * 解密body的密文
     *
     * "resource": {
     *         "original_type": "transaction",
     *         "algorithm": "AEAD_AES_256_GCM",
     *         "ciphertext": "",
     *         "associated_data": "",
     *         "nonce": ""
     *     }
     *
     * @param body
     * @return
     */
    private String decryptBody(String body) throws UnsupportedEncodingException, GeneralSecurityException {

        AesUtil aesUtil = new AesUtil(apiV3Key.getBytes("utf-8"));
        JSONObject object = JSONObject.parseObject(body);
        JSONObject resource = object.getJSONObject("resource");
        String ciphertext = resource.getString("ciphertext");
        String associatedData = resource.getString("associated_data");
        String nonce = resource.getString("nonce");

        return aesUtil.decryptToString(associatedData.getBytes("utf-8"),nonce.getBytes("utf-8"),ciphertext);

    }


    /**
     * 验证签名
     *
     * @param serialNo  微信平台-证书序列号
     * @param signStr   自己组装的签名串
     * @param signature 微信返回的签名
     * @return
     * @throws UnsupportedEncodingException
     */
    private boolean verifiedSign(String serialNo, String signStr, String signature) throws UnsupportedEncodingException {
/*        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        certificatesManager.getVerifier(mchid);
        verifier.verify(serialNo, signStr.getBytes("utf-8"), signature);*/
        return  true;
    }

    /**
     * 转换body为map
     * @param plainBody
     * @return
     */
    private WxPayInfoResp convertWechatPayMsgToMap(String plainBody){
        WxPayInfoResp wxPayInfoResp = JSONObject.parseObject(plainBody, WxPayInfoResp.class);
        return wxPayInfoResp;

    }

    /**
     * 读取请求数据流
     *
     * @param request
     * @return
     */
    private String getRequestBody(HttpServletRequest request) {

        StringBuffer sb = new StringBuffer();

        try (ServletInputStream inputStream = request.getInputStream();
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        ) {
            String line;

            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }

        } catch (IOException e) {
            log.error("读取数据流异常:{}", e);
        }

        return sb.toString();

    }

}
